/*
 * ===================================================================
 *  
 *      Filename:  log_client_protocol_udp.c
 *
 *   Description:  This file is used to send the packet to the remote
 *                 log server with UDP.
 *
 *       Version:  1.0
 *        Create:  2010/07/13
 *
 *        Author:  Keven Zhu     kevenzhu@tencent.com
 *     Copyright:  Reserved by Tencent.com Co.ltd
 *          
 * ====================================================================
 */
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>

#include "lib/util.h"
#include "log_client_api.h"

int global_udp_sock = INV_HANDLER;
extern int global_tcp_sock;

/*main routine for sending the packet in udp*/
int send_log_via_udp(char* msg)
{
    if(global_udp_sock == INV_HANDLER)
    {
        /*send the log to local tmp buffer*/
        log_doctor(doctor_level,"the udp socket was not valid\n");
        goto ERR_SND_UDP;
    }
    if(-1 == send(global_udp_sock,msg,*((short*)msg),0))
    {
        perror("error to send the packet with udp");
        goto ERR_SND_UDP;
    }    
    else
        return NOERR;
ERR_SND_UDP:
    send_log_to_backup(msg);
    return INVIO;
}

/*reinitialize the udp socket*/
int reinit_protocol_udp(unsigned int srv_addr)
{
    int tmp_sock = 0,once_sock = 0;
    struct sockaddr_in serv_addr;
    struct timeval timeo;
    socklen_t len = sizeof(timeo);

    if(srv_addr)
    {
        tmp_sock = socket(AF_INET,SOCK_DGRAM,0);
        if(tmp_sock == -1)
        {
            perror("error to create the socket");
            goto INIT_ERR;
        }
        /*set the timeout value: 2s */
        memset(&timeo,0,sizeof(timeo));
        timeo.tv_sec = 2;
        if (setsockopt(tmp_sock, SOL_SOCKET, SO_SNDTIMEO, &timeo, len) == -1)
        {
            perror("setsockopt");
        }
        /*fill the address field*/
        serv_addr.sin_family = AF_INET;
        serv_addr.sin_port   = htons(HPLOG_SRV_PORT);
        serv_addr.sin_addr.s_addr = htonl(srv_addr);
        bzero(&(serv_addr.sin_zero),8);
        /*connect the socket to the srv*/
        if(connect(tmp_sock, (struct sockaddr*)&serv_addr,sizeof(struct sockaddr))== -1)
        {
            close(tmp_sock);
            perror("error to call the udp connect");
            goto INIT_ERR;
        }
        
        /*I don't whether the udp is ok or not, but I believe TCP is correct!!!  :)*/        
        /*replace the global socket*/
        if(global_tcp_sock != INV_HANDLER)
        {
            once_sock = global_udp_sock;
            global_udp_sock = tmp_sock;
            if(once_sock != INV_HANDLER)
            {
                close(once_sock);
            }
            return NOERR;
        }
        else
        {
            close(tmp_sock);
            log_doctor(doctor_level,"I don't think the udp is ok,set to failure\n");
            goto INIT_ERR;
        }
    }
    else
    {
        /*didn't fine the srv addr*/
        goto INIT_ERR;
    }
INIT_ERR:
    if(global_udp_sock != INV_HANDLER)
        close(global_udp_sock);
    global_udp_sock = INV_HANDLER;   
    return INVIO;
}

int init_protocol_udp()
{
    unsigned int srv_addr = 0;
    /*flush the srv list*/
    //update_destination_addr();
    srv_addr = get_destination();
    reinit_protocol_udp(srv_addr);
    return NOERR;
}

int finit_protocol_udp()
{
    if(global_udp_sock != INV_HANDLER)
        close(global_udp_sock);
    return NOERR;
}
